<template>
    <div class="cropper-content" :key="keys">
        <div class="upload">
            <ul>
                <li
                    v-for="(item, index) in imgList"
                    :key="index"
                    @mouseenter="item.hoverShow = true"
                    @mouseleave="item.hoverShow = false"
                >
                    <img :src="$staticUrl + '/' + item.url" alt="" />
                    <div class="handle-area" v-if="item.hoverShow">
                        <a-icon type="eye" @click="imgShow(item.url)" title="预览文件" />
                        <a-icon v-if="edit" type="delete" @click="deleteFile(index)" title="删除文件" />
                    </div>
                </li>
                <div class="selectImg" v-if="imgList.length < max && edit">
                    <label class="ant-upload-text" :for="'uploads' + keys">
                        <a-icon type="cloud-upload" />
                        选择图片
                    </label>
                    <input
                        type="file"
                        :id="'uploads' + keys"
                        style="position: absolute; clip: rect(0 0 0 0)"
                        accept="image/png, image/jpeg, image/gif, image/jpg"
                        @change="selectImg($event)"
                    />
                </div>
            </ul>
        </div>
        <div class="mask" v-if="show">
            <div class="warp">
                <div class="title">
                    <p>裁剪图片</p>
                    <a-icon type="close" @click="handleClose" />
                </div>
                <div class="cropper">
                    <vue-cropper
                        ref="cropper"
                        :img="option.img"
                        :outputSize="option.outputSize"
                        :outputType="option.outputType"
                        :info="option.info"
                        :canScale="option.canScale"
                        :autoCrop="option.autoCrop"
                        :autoCropWidth="option.autoCropWidth"
                        :autoCropHeight="option.autoCropHeight"
                        :fixed="option.fixed"
                        :fixedNumber="option.fixedNumber"
                        :full="option.full"
                        :fixedBox="option.fixedBox"
                        :canMove="option.canMove"
                        :canMoveBox="option.canMoveBox"
                        :original="option.original"
                        :centerBox="option.centerBox"
                        :height="option.height"
                        :infoTrue="option.infoTrue"
                        :maxImgSize="option.maxImgSize"
                        :enlarge="option.enlarge"
                        :mode="option.mode"
                        @realTime="realTime"
                        @imgLoad="imgLoad"
                    >
                    </vue-cropper>
                </div>
                <!--底部操作工具按钮-->
                <div class="footer-btn">
                    <div class="scope-btn">
                        <a-button @click="changeScale(1)">+ 放大 </a-button>
                        <a-button @click="changeScale(-1)">- 缩小 </a-button>
                        <a-button @click="rotateLeft">↺ 左旋转</a-button>
                        <a-button @click="rotateRight">↻ 右旋转</a-button>
                    </div>
                    <div class="upload-btn">
                        <a-button type="primary" @click="uploadImg('blob')" v-prevent-re-click>
                            上传图片 <a-icon type="cloud-upload" />
                        </a-button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
import { getUUID } from '@/plugins/tools'
export default {
    name: 'CropperImage',
    model: {
        prop: 'value',
        event: 'change'
    },
    props: {
        value: {
            type: Array,
            default: () => {
                return []
            }
        },
        width: {
            type: Number,
            default: 400
        },
        height: {
            type: Number,
            default: 262
        },
        max: {
            type: Number,
            default: 1
        },
        fileSize: {
            type: Number,
            default: 1
        },
        path: {
            type: String,
            default: ''
        },
        keys: {
            type: String,
            default: ''
        },
        edit: {
            type: Boolean,
            default: () => {
                return true
            }
        }
    },
    data () {
        return {
            show: false,
            imgList: [],
            sourceList: [],
            previews: {},
            option: {
                img: '', // 裁剪图片的地址
                outputSize: 1, // 裁剪生成图片的质量(可选0.1 - 1)
                outputType: 'jpeg', // 裁剪生成图片的格式（jpeg || png || webp）
                info: true, // 裁剪框的大小信息，图片大小信息
                canScale: true, // 图片是否允许滚轮缩放
                autoCrop: true, // 是否默认生成截图框
                autoCropWidth: this.width, // 默认生成截图框宽度
                autoCropHeight: this.height, // 默认生成截图框高度
                fixed: false, // 是否开启截图框宽高固定比例
                fixedNumber: [1.5, 1], // 截图框的宽高比例
                full: false, // false按原比例裁切图片，不失真
                fixedBox: true, // 固定截图框大小，不允许改变
                canMove: true, // 上传图片是否可以移动
                canMoveBox: true, // 截图框能否拖动
                original: true, // 上传图片按照原始比例渲染
                centerBox: true, // 截图框是否被限制在图片里面
                height: true, // 是否按照设备的dpr 输出等比例图片
                infoTrue: false, // true为展示真实输出图片宽高，false展示看到的截图框宽高
                maxImgSize: 1080, // 限制图片最大宽度和高度
                enlarge: 1 // 图片根据截图框输出比例倍数
                // mode: '400px 262px' // 图片默认渲染方式
            }
        }
    },
    watch: {
        value: {
            deep: true,
            immediate: true,
            handler (val) {
                if (val === null || val === [] || val === undefined) {
                    return []
                }
                this.$nextTick(() => {
                    this.imgList = val.map((item) => {
                        return {
                            url: item,
                            hoverShow: false
                        }
                    })
                    this.sourceList = this.imgList.map(item => item.url)
                })
            }
        }
    },
    methods: {
        // 初始化函数
        imgLoad (msg) {},
        // 图片缩放
        changeScale (num) {
            num = num || 1
            this.$refs.cropper.changeScale(num)
        },
        // 向左旋转
        rotateLeft () {
            this.$refs.cropper.rotateLeft()
        },
        // 向右旋转
        rotateRight () {
            this.$refs.cropper.rotateRight()
        },
        // 实时预览函数
        realTime (data) {
            this.previews = data
        },
        // 选择图片
        selectImg (e) {
            const file = e.target.files[0]
            // 转化为blob
            const reader = new FileReader()
            reader.onload = (e) => {
                let data = ''
                if (typeof e.target.result === 'object') {
                    data = window.URL.createObjectURL(new Blob([e.target.result]))
                } else {
                    data = e.target.result
                }
                this.option.img = data
                this.show = true
            }
            // 转化为base64
            reader.readAsDataURL(file)
        },
        // 上传图片
        uploadImg (type) {
            if (type === 'blob') {
                // 获取截图的blob数据
                this.$refs.cropper.getCropBlob((file) => {
                    const fileSize = file.size / 1024 / 1024 < this.fileSize
                    if (!fileSize) {
                        this.$message.error(`图片大小不能超过${this.fileSize}M!`)
                        return false
                    }
                    const _path = '/' + this.path + '/' + this.$service.dateFormatter('yyyy-MM-dd') + '/'
                    this.$service
                        .getAuthor({ Method: 'POST', Pathname: '/' })
                        .then((info) => {
                            const formData = new FormData()
                            const _key = _path + getUUID() + '.' + file.type
                            formData.append('signature', info.Authorization)
                            formData.append('x-cos-security-token', info.XCosSecurityToken)
                            formData.append('Content-Type', '')
                            formData.append('key', _key)
                            formData.append('dir', _path)
                            formData.append('host', this.$staticUrl)
                            formData.append('file', file)
                            this.$ApiServer
                                .uploadFileCos(formData)
                                .then((res) => {
                                    if (res === '') {
                                        this.sourceList.push(_key)
                                        this.$emit('change', this.sourceList)
                                        this.show = false
                                    } else {
                                        this.$message.error('上传失败,请重新上传')
                                    }
                                })
                                .catch(() => {
                                    this.$message.error('上传失败')
                                })
                        })
                        .catch(() => {
                            this.$message.error('上传失败')
                        })
                })
            }
        },
        handleClose () {
            this.show = false
        },
        imgShow (url) {
            const urls = url.split(',')
            this.$picturesModal({ urls })
        },
        deleteFile (index) {
            const that = this
            return new Promise((resolve, reject) => {
                this.$confirm({
                    title: '提示',
                    content: '您确认要删除图片重新上传吗？',
                    okText: '确认',
                    okType: 'primary',
                    cancelText: '取消',
                    onOk () {
                        that.imgList.splice(index, 1)
                        const temp = that.imgList.map(item => item.url)
                        that.$emit('change', temp)
                    },
                    onCancel () {
                        return resolve(false)
                    }
                })
            })
        }
    }
}
</script>
<style scoped lang="less">
.cropper-content {
    .upload {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        ul {
            display: flex;
            flex-wrap: wrap;
            li {
                width: 2rem;
                height: 1.4rem;
                margin-right: 8px;
                margin-bottom: 8px;
                border-radius: 4px;
                border: 1px solid #d4d4d4;
                overflow: hidden;
                position: relative;
                img {
                    width: 100%;
                    height: 100%;
                    object-fit: cover;
                }
                .handle-area {
                    width: 100%;
                    height: 100%;
                    position: absolute;
                    top: 0;
                    left: 0;
                    z-index: 2;
                    background: rgba(0, 0, 0, 0.5);
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    i {
                        color: rgba(255, 255, 255, 0.85);
                        font-size: 16px;
                        cursor: pointer;
                        & + i {
                            margin-left: 10px;
                        }
                    }
                }
            }
        }
        .selectImg {
            width: 2rem;
            height: 1.4rem;
            margin-bottom: 8px;
            &:hover {
                ::v-deep {
                    .anticon-cloud-upload svg {
                        color: @primary-color;
                    }
                    .ant-upload-text {
                        color: @primary-color !important;
                        border: 1px solid @primary-color;
                    }
                }
            }
            .anticon-cloud-upload {
                color: #999999;
                font-size: 0.3rem;
            }
            .ant-upload-text {
                display: block;
                width: 100%;
                height: 100%;
                color: #999999;
                font-size: 0.14rem;
                border-radius: 4px;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;
                border: 1px solid #d4d4d4;
                cursor: pointer;
            }
        }
    }
}
.mask {
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    position: fixed;
    top: 0;
    left: 0;
    z-index: 900;
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: auto;
    .warp {
        width: 60%;
        height: 710px;
        border-radius: 4px;
        background-color: #fff;
        overflow: hidden;
        .title {
            width: 100%;
            padding: 16px;
            color: rgba(0, 0, 0, 0.65);
            background: #fff;
            border-bottom: 1px solid #e8e8e8;
            display: flex;
            justify-content: space-between;
            align-items: center;
            p {
                color: rgba(0, 0, 0, 0.85);
                font-weight: 500;
                font-size: 16px;
                line-height: 22px;
                word-wrap: break-word;
            }
            .anticon {
                font-size: 20px;
                cursor: pointer;
            }
        }
        .cropper {
            min-width: 600px;
            height: 600px;
            padding: 16px;
        }
        .footer-btn {
            padding: 0 16px;
            display: flex;
            justify-content: space-between;
        }
    }
}
</style>
